<template>
  <div class="home">
    <div class="top">
      <img src="/src/assets/images/icon.png" alt="" />
      <span>ROS 2编程框架</span>
    </div>
    <div class="main">
      <div class="main-content">
        <div class="mc-t">
          <div
            class="mct-left"
            :style="
              stepList.length === answerList.length ? { width: '100%' } : ''
            "
          >
            <div class="mctl-top">
              <SvgIcon name="point" size="32" />
              <SvgIcon name="close" />
            </div>
            <pre class="mctl-content">
import sys, select, termios, tty

# 操作方式--(全部都是小写）
# i前进 ,k后退 j左转，l右转
# t 线速度和角速度放大 1.1 倍，y 线速度和角速度缩小 0.9 倍 
# g 线速度放大 1.1 倍，h 线速度缩小 0.9 倍 
# b 角速度放大 1.1 倍，n 角速度缩小 0.9 倍 
# 除去以上按钮、 任意键停止， 
class ExampleInterfacesRobot02(Node):
    def __init__(self,name):
        # 新建控制服务节点
        super().__init__(name) # 创建客户端节点
        self.get_logger().info("节点已启动：%s!" % name)
        
        # 调用小车移动功能类
        self.robot = Robot(self)
        
        # 创建客户端实例
        self.command_subscribe_ = <pre :class="['hole', isEnd && answers[0].index !== 0 ? 'error' : '', isEnd && preview === 0 ? 'border-err': '']"
        @drop="handleDrop(1)" @dragover.prevent>{{ answers[0].index !== -1 ? answerList.find((item:any) => item.id - 1 === answers[0].index)?.content : '' }}</pre>
            def handle_move_robot(self,msg):
            self.get_logger().info(f"接收到请求: {msg.data}")
            try:
            # 调用小车移动功能<pre :class="['hole', isEnd && answers[1].index !== 1 ? 'error' : '', isEnd && preview === 1 ? 'border-err': '']" @drop="handleDrop(2)"
              @dragover.prevent>{{ answers[1].index !== -1 ? answerList.find((item:any) => item.id - 1 === answers[1].index)?.content : '' }}</pre>
            self.get_logger().info("服务端处理成功")
            except Exception as e:
            self.get_logger().error(f"处理请求时发生异常: {e}")

            def main(args=None):
            rclpy.init(args=args) # 初始化rclpy
            node = <pre :class="['hole', isEnd && answers[2].index !== 2 ? 'error' : '', isEnd && preview === 2 ? 'border-err': '']" @drop="handleDrop(3)"
              @dragover.prevent>{{ answers[2].index !== -1 ? answerList.find((item:any) => item.id - 1 === answers[2].index)?.content : '' }}</pre>
            # 保持节点运行，检测是否收到退出指令（Ctrl+C）<pre :class="['hole', isEnd && answers[3].index !== 3 ? 'error' : '', isEnd && preview === 3 ? 'border-err': '']" @drop="handleDrop(4)"
              @dragover.prevent>{{ answers[3].index !== -1 ? answerList.find((item:any) => item.id - 1 === answers[3].index)?.content : '' }}</pre>
            # 关闭rclpy<pre :class="['hole', isEnd && answers[4].index !== 4 ? 'error' : '', isEnd && preview === 4 ? 'border-err': '']" @drop="handleDrop(5)"
              @dragover.prevent>{{ answers[4].index !== -1 ? answerList.find((item:any) => item.id - 1 === answers[4].index)?.content : '' }}</pre></pre>
          </div>
          <div class="mct-right" v-show="stepList.length !== answerList.length">
            <div class="mctr-top">
              <div class="mctrt-circle">&lt;/&gt;</div>
            </div>
            <div class="mctr-content">
              <template v-for="item in answerList" :key="item.id">
                <div
                  class="mctrc-item"
                  draggable="true"
                  :style="
                    !stepList.includes(item.id - 1)
                      ? { opacity: '1' }
                      : { opacity: '0' }
                  "
                  @dragstart="handleDragStart(item.id)"
                >
                  {{ item.content }}
                </div>
              </template>
            </div>
          </div>
        </div>
        <div class="mc-b">
          <div class="mcb-1"></div>
          <div class="mcb-2"></div>
          <div class="mcb-3"></div>
          <div class="mcb-4"></div>
          <div class="analyze">
            <p class="analyze-title">解析：</p>
            <p class="analyze-content">
              {{
                isEnd
                  ? answerList.find((item: any) => item.id - 1 === preview)
                      ?.analyze
                  : ''
              }}
            </p>
          </div>
        </div>
      </div>
      <div class="main-btn">
        <!-- <div class="btn b1" v-if="!isEnd" @click="handleCancel">
          <SvgIcon name="back" size="18" style="margin-right: 4px" />
          撤销
        </div> -->
        <div class="btn b2" v-if="!isEnd" @click="handleSubmit">
          <SvgIcon name="finish" size="18" style="margin-right: 4px" />
          提交
        </div>
        <div class="btn b3" v-if="isEnd" @click="handleNext">
          <SvgIcon name="next" size="18" style="margin-right: 4px" />
          下一处
        </div>
        <div class="btn b4" v-if="isEnd" @click="handleAgain">
          <SvgIcon name="again" size="18" style="margin-right: 4px" />
          重新作答
        </div>
      </div>
    </div>
    <Dialog ref="dialogRef" />
  </div>
</template>

<script setup lang="ts">
import Dialog from './components/dialog.vue'

const dialogRef = ref()

// 右侧的答案列表
const answerList = ref<any>([
  {
    id: 3,
    content: 'ExampleInterfacesRobot02("subscripition_moveRobot")',
    analyze: '创建并初始化机器人对象',
  },
  {
    id: 1,
    content:
      'self.create_subscription(String,"move_robot",self.handle_move_robot,10)',
    analyze: '订阅消息，创建订阅实例',
  },
  { id: 5, content: 'rclpy.shutdown()', analyze: '节点循环结束，关闭节点资源' },
  {
    id: 2,
    content: 'self.robot.moveRobot(msg.data)',
    analyze: '机器人小车解析消息并执行运动',
  },

  { id: 4, content: 'rclpy.spin(node)', analyze: '启动一个节点的主循环' },
])

// 左侧答案列表
const answers = ref<any>([
  { index: -1 },
  { index: -1 },
  { index: -1 },
  { index: -1 },
  { index: -1 },
])

// 步骤
const stepList = ref<any>([])

// 记录位置
const position = ref<any>([])

// 当前拖拽
const dragNum = ref<any>(null)

// 是否结束
const isEnd = ref<boolean>(false)

// 结束后的预览位置定位
const preview = ref<number>(0)

// 拖拽开始
const handleDragStart = (index: number) => {
  dragNum.value = index - 1
}

// 拖拽结束
const handleDrop = (index: number) => {
  // 记录步骤
  stepList.value.push(dragNum.value)
  // 记录位置，并且不重复
  if (!position.value.includes(index - 1)) {
    position.value.push(index - 1)
  }

  // 如果当前移入的位置有数据
  if (answers.value[index - 1].index !== -1) {
    // 删除之前记录的步骤
    stepList.value.splice(
      stepList.value.indexOf(answers.value[index - 1].index),
      1,
    )
  }

  answers.value[index - 1].index = dragNum.value
}

// 撤销
// const handleCancel = () => {
//   if (stepList.value.length > 0) {
//     // 根据步骤列表最后一个来删除记录
//     answers.value[position.value[position.value.length - 1]].index = -1
//     // 步骤列表最后一个删除
//     stepList.value.splice(stepList.value.length - 1, 1)
//     // 位置列表最后一个删除
//     position.value.splice(position.value.length - 1, 1)
//   }
// }

// 提交
const handleSubmit = () => {
  // 是否全部填写
  if (stepList.value.length === answerList.value.length) {
    isEnd.value = true
    let count = 0
    answers.value.forEach((item: any, index: number) => {
      if (item.index !== index) {
        count++
      }
    })
    dialogRef.value.showFn(count)
  } else {
    ElMessage.error('请填写全部题目！')
  }
}

// 下一步
const handleNext = () => {
  // 不超出范围内+1，否则回到0
  if (preview.value < answerList.value.length - 1) {
    preview.value++
  } else {
    preview.value = 0
  }
}

// 重新作答
const handleAgain = () => {
  isEnd.value = false
  for (let i = 0; i < answers.value.length; i++) {
    answers.value[i].index = -1
  }
  preview.value = 0
  stepList.value = []
  position.value = []
}
</script>

<style lang="scss" scoped>
.home {
  width: 100%;
  height: 100%;
  min-height: 500px;
  user-select: none;

  .top {
    position: relative;
    width: 100%;
    height: 10%;
    display: flex;
    align-items: center;
    background: url(/src/assets/images/top-bg.png) no-repeat center;
    background-size: cover;
    padding-left: 3vw;
    box-shadow: 0 10px 10px rgba(0, 0, 0, 0.15);
    z-index: 1;

    span {
      font-size: 24px;
      color: #3880e4;
      font-weight: 600;
      display: flex;
      align-items: center;
      margin-left: 8px;
    }

    img {
      width: auto;
      height: 80%;
    }
  }

  .main {
    height: 90%;
    background: url(/src/assets/images/main-bg.png) no-repeat center;
    background-size: cover;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 24px;
    padding-bottom: 8px;

    .main-content {
      height: 90%;
      width: 100%;

      .mc-t {
        height: 80%;
        width: 100%;
        border: 6px solid #ceeaff;
        border-radius: 4px;
        box-shadow: 0 0 0 12px #5b69a6;
        display: flex;
        overflow: hidden;
        background-color: #ceeaff;

        .mct-left {
          width: 65%;
          background-color: #fff;

          .mctl-top {
            height: 20px;
            display: flex;
            padding: 0 8px;
            justify-content: space-between;
            align-items: center;
            background-color: #819ce1;
          }

          .mctl-content {
            height: calc(100% - 16px);
            background-color: #fff;
            padding: 12px 8px;
            overflow: auto;
            font-size: 14px;
            white-space: pre-wrap;
            word-wrap: break-word;

            .hole {
              background-color: #cde7fe;
              padding: 6px 12px;
              margin: 0 60px;
              border-radius: 4px;
              min-height: 33px;
              min-width: 100px;
              max-width: calc(100% - 120px);
              width: fit-content;
              white-space: pre-wrap;
            }

            .error {
              color: #ff0000;
            }

            .border-err {
              border: 5px ridge #ff0000;
            }
          }
        }

        .mct-right {
          width: calc(35% - 8px);
          margin-left: 8px;
          background-color: green;

          .mctr-top {
            padding-left: 8px;
            height: 20px;
            background-color: #819ce1;
            overflow: hidden;

            .mctrt-circle {
              height: 100%;
              width: 20px;
              border-radius: 50%;
              font-size: 10px;
              display: flex;
              justify-content: center;
              align-items: center;
              color: #6488d4;
              font-weight: 600;
              background-color: #dfe6fc;
            }
          }

          .mctr-content {
            height: calc(100% - 16px);
            background-color: #6488d4;
            padding: 12px;
            // overflow: auto;
            display: flex;
            flex-direction: column;

            .mctrc-item {
              flex: 1;
              width: 100%;
              cursor: pointer;
              word-wrap: break-word;
              padding: 4px 8px;
              font-size: 13px;
              background-color: #fff;
              margin-bottom: 12px;
              color: #2563eb;
              border-radius: 4px;
            }

            :last-child {
              margin-bottom: 0;
            }

            &::-webkit-scrollbar-track {
              background-color: #fff;
            }

            &::-webkit-scrollbar-thumb {
              border-radius: 0;
              background-color: #ccc;
            }

            &::-webkit-scrollbar-thumb:hover {
              background-color: #aaa;
            }
          }
        }
      }

      .mc-b {
        position: relative;
        height: calc(20% - 12px);
        width: 100%;
        display: flex;
        margin-top: 12px;
        flex-direction: column;
        align-items: center;

        .mcb-1 {
          height: 20%;
          width: 20%;
          background-color: #7088d0;
        }

        .mcb-2 {
          height: 30%;
          width: 25%;
          background-color: #91a7df;
          clip-path: polygon(10% 0%, 90% 0%, 100% 100%, 0% 100%);
        }

        .mcb-3 {
          height: 40%;
          width: 50%;
          background-color: #a7caec;
          clip-path: polygon(10% 0%, 90% 0%, 100% 100%, 0% 100%);
        }

        .mcb-4 {
          height: 10%;
          width: 50%;
          background-color: #c7e9fd;
        }

        .analyze {
          top: 20%;
          width: 100%;
          height: 80%;
          background-color: rgba(255, 255, 255, 0.6);
          position: absolute;
          border-radius: 12px;
          border: 2px solid #7db0fd;
          padding: 6px 12px;
          font-size: 18px;
          display: flex;

          .analyze-title {
            color: #0b6bf2;
            font-weight: 600;
          }

          .analyze-content {
            display: inline-block;
            margin-top: 8px;
            margin-left: 8px;
          }
        }
      }
    }

    .main-btn {
      height: 10%;
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 32px;

      .btn {
        cursor: pointer;
        height: 38px;
        width: 120px;
        border-radius: 38px;
        display: flex;
        align-items: center;
        justify-content: center;
        color: #fff;
        fill: #fff;
        background-color: #fff;
      }

      .b1 {
        background-color: #409eff;
      }

      .b2 {
        background-color: #27ce9b;
      }

      .b3 {
        background-color: #fab344;
      }

      .b4 {
        background-color: #f2642c;
      }
    }
  }
}
</style>
